package best.driver.android.NetBase;

import android.app.IntentService;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import best.driver.android.AppConfig;
import best.driver.android.AppInfo;
import best.driver.android.BestApp;
import best.driver.android.Map.location.LocationManager;
import best.driver.android.R;
import best.driver.android.Utils.PhoneFunc;
import best.driver.android.common.app.AppProxyFactory;
import best.driver.android.manager.UserInfoManager;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;

public class BackService extends Service {
    private static final String TAG = "BackService";
    private static final long HEART_BEAT_RATE = 30 * 1000;

    public static final int PORT = AppProxyFactory.getProxy().getAppConfig().getSocketPort();

    public static final String MESSAGE_ACTION = "org.feng.message_ACTION";
    public static final String HEART_BEAT_ACTION = "org.feng.heart_beat_ACTION";
    public static final String PUSH_MESSAGE_ACTION = "org.feng.push_message_ACTION";

    private ReadThread mReadThread;

    private LocalBroadcastManager mLocalBroadcastManager;

    private WeakReference<Socket> mSocket;

    // For heart Beat
    private Handler mHandler = new Handler();
    private Runnable heartBeatRunnable = new Runnable() {

        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                boolean isSuccess = sendMsg(null);
                if (!isSuccess) {
                    mHandler.removeCallbacks(heartBeatRunnable);
                    mReadThread.release();
                    releaseLastSocket(mSocket);
                    new InitSocketThread().start();
                }
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);
        }
    };

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            final String action = intent.getAction();
            if (MESSAGE_ACTION.equals(action)) {
                String content = intent.getStringExtra("message");
                if (!TextUtils.isEmpty(content)) {
                    sendMsg(content);
                } else {
                    sendMsg(null);
                }
                Log.d("Message", action);
            }
        }
    };

    private long sendTime = 0L;


    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        new InitSocketThread().start();
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
        IntentFilter filter = new IntentFilter();
        filter.addAction(MESSAGE_ACTION);
        filter.addAction(HEART_BEAT_ACTION);
        registerReceiver(mReceiver, filter);
        Log.d("broadhaha", "dasfsfdsf");

    }

    public boolean sendMsg(String msg) {
        if (null == mSocket || null == mSocket.get()) {
            releaseLastSocket(mSocket);
            new InitSocketThread().start();
            return false;
        }
        String tt = UserInfoManager.getInstance().getDriverId();
        String iMei = PhoneFunc.getImei();
        Socket soc = mSocket.get();
        try {
            if (!soc.isClosed() && !soc.isOutputShutdown()) {
                if (TextUtils.isEmpty(msg)) {
                    OutputStream os = soc.getOutputStream();
                    BufferedOutputStream bos = new BufferedOutputStream(os, 2 * 1024);
                    msg = tt + ",D,1";
                    ByteBuffer byteBuffer = ByteBuffer.allocate(74 + msg.length());
                    byteBuffer.putInt(0xabcd0100);
                    byteBuffer.put((byte) 11);
                    byteBuffer.put((byte) 0);
                    ByteBuffer bb = ByteBuffer.allocate(64);
                    Log.d("ImeiLength", "" + iMei.getBytes().length);
                    bb.put(iMei.getBytes());
                    Log.d("ImeiLengthll", "" + bb.array().length);
                    byteBuffer.put(bb.array());
                    byteBuffer.putInt(msg.getBytes().length);
                    byteBuffer.put(msg.getBytes());
                    bos.write(byteBuffer.array());
                    bos.flush();
                    Log.d("login_code: ", byteBuffer.toString());
                    sendTime = System.currentTimeMillis();
                    BestApp.getInstance().uploadPosition();
                } else {
                    if(!UserInfoManager.getInstance().isLogin() || !UserInfoManager.getInstance().isCheckSucceed()) {
                        return true;
                    }
                    OutputStream os = soc.getOutputStream();
                    BufferedOutputStream bos = new BufferedOutputStream(os, 2 * 1024);
                    ByteBuffer byteBuffer = ByteBuffer.allocate(74 + msg.length());
                    byteBuffer.putInt(0xabcd0100);
                    byteBuffer.put((byte) 13);
                    byteBuffer.put((byte) 0);
                    ByteBuffer bb = ByteBuffer.allocate(64);
                    Log.d("ImeiLength", "" + iMei.getBytes().length);
                    bb.put(iMei.getBytes());
                    Log.d("ImeiLengthll", "" + bb.array().length);
                    byteBuffer.put(bb.array());
                    byteBuffer.putInt(msg.getBytes().length);
                    byteBuffer.put(msg.getBytes());

                    bos.write(byteBuffer.array());

                    bos.flush();
                    sendTime = System.currentTimeMillis();
                }
                Log.d("MessageTrue", msg);
            } else {
                Log.d("soketFalse", "断开");
                return false;
            }
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            Log.d("soketFalse", "超时");

            return false;
        } catch (IOException e) {
            e.printStackTrace();
            Log.d("soketFalse", "异常");

            return false;
        }
        return true;
    }

    private void initSocket() {
        try {
            Socket so = new Socket(AppProxyFactory.getProxy().getAppConfig().getSocketHostUrl(), PORT);
            mSocket = new WeakReference<Socket>(so);
            mReadThread = new ReadThread(so);
            mReadThread.start();
            mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.d("exception", e.getMessage());
        }
    }

    private void releaseLastSocket(WeakReference<Socket> mSocket) {
        try {
            if (null != mSocket) {
                Socket sk = mSocket.get();
                if (sk != null && !sk.isClosed()) {
                    sk.close();
                }
                sk = null;
                mSocket = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class InitSocketThread extends Thread {
        @Override
        public void run() {
            super.run();
            initSocket();
        }
    }

    // Thread to read content from Socket
    class ReadThread extends Thread {
        private WeakReference<Socket> mWeakSocket;
        private boolean isStart = true;

        public ReadThread(Socket socket) {
            mWeakSocket = new WeakReference<Socket>(socket);
        }

        public void release() {
            isStart = false;
            releaseLastSocket(mWeakSocket);
        }

        @Override
        public void run() {
            super.run();
            Socket socket = mWeakSocket.get();
            if (null != socket) {
                try {
                    InputStream is = socket.getInputStream();
                    SocketMessage socketMessage = new SocketMessage();
                    SocketHeader socketHeader = new SocketHeader();
                    int length = 0;
                    byte[] buffer = new byte[1024 * 1024];
                    while (!socket.isClosed() && !socket.isInputShutdown()
                            && isStart && ((length = is.read(buffer)) != -1)) {
                        if (length > 0) {
                            int crcCode = bytesToInt(buffer, 0);
                            socketHeader.setCrcCode(crcCode);

                            byte type = buffer[4];
                            socketHeader.setType(type);

                            byte priority = buffer[5];
                            socketHeader.setPriority(priority);

                            int textLength = bytesToInt(buffer, 70);
                            socketHeader.setLength(textLength);

                            socketMessage.setHeader(socketHeader);
                            if (length > 0) {
                                if (textLength < buffer.length) {
                                    socketMessage.setBody(new String(buffer, 74, textLength));
                                } else {
                                    System.out.println("继续等待下一个缓冲区");
                                }
                            }
                            Intent intent = new Intent();
                            intent.setAction(BackService.PUSH_MESSAGE_ACTION);
                            intent.putExtra("type", socketMessage.getHeader().getType());
                            intent.putExtra("length", socketMessage.getHeader().getLength());
                            if(socketMessage.getBody() != null) {
                                intent.putExtra("content", socketMessage.getBody().toString());
                            }
                            sendBroadcast(intent);

                            Log.d("getMessageRead", socketMessage.toString());
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
        startService(new Intent(this, BackService.class));
    }

    /**
     * byte数组中取int数值，本方法适用于(低位在后，高位在前)的顺序
     *
     * @param src
     * @param offset
     * @return
     */
    public static int bytesToInt(byte[] src, int offset) {
        int value = (src[offset] & 0xFF) << 24;
        value = value | ((src[offset + 1] & 0xFF) << 16);
        value = value | ((src[offset + 2] & 0xFF) << 8);
        value = value | (src[offset + 3] & 0xFF);
        return value;
    }

    /**
     * 将int数值转换为占四个字节的byte数组，本方法适用于(高位在前，低位在后)的顺序
     *
     * @param value
     * @return
     */
    public static byte[] intToBytes(int value) {
        byte[] src = new byte[4];
        src[0] = (byte) ((value >> 24) & 0xFF);
        src[1] = (byte) ((value >> 16) & 0xFF);
        src[2] = (byte) ((value >> 8) & 0xFF);
        src[3] = (byte) (value & 0xFF);
        return src;
    }

}
